

package jetbrains.buildServer.server.rest.model.deployment;

import java.util.HashMap;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import jetbrains.buildServer.server.rest.model.Fields;
import jetbrains.buildServer.server.rest.swagger.annotations.ModelDescription;
import jetbrains.buildServer.server.rest.util.BeanContext;
import jetbrains.buildServer.server.rest.util.ValueWithDefault;
import jetbrains.buildServer.serverSide.deploymentDashboards.DeploymentDashboardManager;
import jetbrains.buildServer.serverSide.deploymentDashboards.entities.DeploymentDashboard;
import jetbrains.buildServer.serverSide.deploymentDashboards.entities.DeploymentInstance;
import jetbrains.buildServer.serverSide.deploymentDashboards.entities.DeploymentState;
import jetbrains.buildServer.serverSide.deploymentDashboards.exceptions.DashboardNotFoundException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

@XmlRootElement(name = "deploymentInstance")
@ModelDescription(
  value = "Represents an instance that has been deployed to external system, along with deployment history."
)
public class Instance {

  @XmlAttribute
  public String id;
  @XmlElement(name = "deploymentStateEntries")
  public StateEntries deploymentStateEntries;
  @XmlAttribute
  public DeploymentState currentState;
  @XmlElement
  public HashMap<String, String> attributes;
  @XmlElement(name = "deploymentDashboard")
  public Dashboard deploymentDashboard;

  public Instance() {
  }

  public Instance(
    @NotNull final DeploymentInstance deploymentInstance,
    @NotNull final Fields fields,
    @NotNull final BeanContext beanContext
  ) {
    id = ValueWithDefault.decideIncludeByDefault(
      fields.isIncluded("id"),
      deploymentInstance.getId()
    );

    deploymentStateEntries = ValueWithDefault.decideDefault(
      fields.isIncluded("deploymentStateEntries", false),
      resolveDeploymentStateEntries(deploymentInstance, fields, beanContext)
    );

    currentState = ValueWithDefault.decideIncludeByDefault(
      fields.isIncluded("currentState"),
      deploymentInstance.getCurrentState()
    );

    attributes = (HashMap<String, String>)ValueWithDefault.decideIncludeByDefault(
      fields.isIncluded("attributes"),
      deploymentInstance.getAttributes()
    );

    if (fields.isIncluded("deploymentDashboard", true, true)) {
      deploymentDashboard = resolveDeploymentDashboard(deploymentInstance, fields, beanContext);
    }
  }

  @NotNull
  private static StateEntries resolveDeploymentStateEntries(@NotNull DeploymentInstance deploymentInstance, @NotNull Fields fields, @NotNull BeanContext beanContext) {
    Fields nestedFields = fields.getNestedField("deploymentStateEntries", Fields.NONE, Fields.LONG);

    return new StateEntries(
      deploymentInstance.getKnownStates(),
      nestedFields,
      beanContext
    );
  }

  @Nullable
  private static Dashboard resolveDeploymentDashboard(@NotNull DeploymentInstance deploymentInstance, @NotNull Fields fields, @NotNull BeanContext beanContext) {
    try {
      DeploymentDashboard dashboard = beanContext
        .getSingletonService(DeploymentDashboardManager.class)
        .getDashboard(deploymentInstance.getDashboardId());

      return new Dashboard(
        dashboard,
        fields.getNestedField("deploymentDashboard"),
        beanContext
      );
    } catch (DashboardNotFoundException e) {
      return null;
    }
  }
}